import { FC, useEffect, useState, useRef, useSyncExternalStore } from "react";
import { observer, inject } from "mobx-react";
import {
  Button,
  Drawer,
  Layout,
  Space,
  Table,
  Modal,
  Select,
  Divider,
  Tooltip,
  Dropdown,
  Row,
  Col,
} from "antd";
import type { MenuProps, SelectProps } from "antd";
import {
  PlusOutlined,
  ClearOutlined,
  DeleteOutlined,
  GroupOutlined,
  CopyOutlined,
  CaretRightOutlined,
  CaretLeftOutlined,
  VerticalAlignBottomOutlined,
  PlusSquareOutlined,
  MoreOutlined,
} from "@ant-design/icons";
import _ from "lodash";
import {
  transformArray,
  getReversedBefore,
  swapElementPosition
} from "../../utils";
import { ITStore } from "../../store";
import { ITColumns } from "../../store/interfaces";
interface TProp {
  store: ITStore;
  edigReagentClick: () => void;
}

const { Content } = Layout;

const TEMPTIME = "Temp/Time";

const ReagentHeaderModal = inject("store")(
  observer(({ store, open, close }: TProp | any) => {
    const {
      languageStore: { lang, langCur },
      reagentStore: { getReagentInfoById, allReagent },
      designerStore: {
        delDataReactorReagent,
        currentDesigner,
        reactionDrawerData,
        updateReactDesigner,
        changeReactionDrawerData,
      },
    } = store;

    const [options, setOptions] = useState<any>([]);

    const [selectValue, setSelectValue] = useState<any>(null);

    const handleCancel = () => {
      close();
    };

    const addAll = async () => {
      const { _id, reagentsort } = reactionDrawerData;
      let nextReagentsort: string[] = [];
      if (options && options.length) {
        const reagentList = options[1].options;
        const reagentIds = reagentList.map((item: any) => item.value);
        nextReagentsort = [...reagentsort, ...reagentIds];
      }
      if (nextReagentsort && nextReagentsort.length) {
        const param = {
          id: _id,
          reagentsort: nextReagentsort,
        };
        const res = await updateReactDesigner(param);
        if (!res) {
          handleCancel();

          changeReactionDrawerData({
            ...reactionDrawerData,
            reagentsort: nextReagentsort,
          });
        }
      }
    };

    const handleOk = async () => {
      const { _id, reagentsort } = reactionDrawerData;
      if (selectValue) {
        const nextReagentsort = [...reagentsort, selectValue.value];
        const param = {
          id: _id,
          reagentsort: nextReagentsort,
        };
        const res = await updateReactDesigner(param);
        if (!res) {
          handleCancel();

          changeReactionDrawerData({
            ...reactionDrawerData,
            reagentsort: nextReagentsort,
          });
        }
      }
    };

    const onSelect = (value: any) => {
      setSelectValue(value);
    };

    useEffect(() => {
      if (open && currentDesigner && reactionDrawerData) {
        const { reagents } = currentDesigner;
        const reagentIdSets = new Set();
        if (reagents) {
          const plateValues = Object.values(reagents);
          if (plateValues.length) {
            plateValues.forEach((plateValue: any) => {
              const slotValues = Object.values(plateValue);
              if (slotValues.length) {
                slotValues.forEach((slotValue: any) => {
                  reagentIdSets.add(slotValue.reagentId);
                  // const reagentInfo = getReagentInfoById(slotValue.reagentId);
                });
              }
            });
          }
        }

        const reagentIds = Array.from(reagentIdSets);

        const tempOptions: any = [
          {
            label: lang["langtmptime"],
            options: [
              {
                key: TEMPTIME,
                label: TEMPTIME,
                value: TEMPTIME,
              },
            ],
          },
        ];
        if (reagentIds.length) {
          const reagentOptions: any = [];
          reagentIds.forEach((reagentId) => {
            const reagentInfo = getReagentInfoById(reagentId);
            // 先取简称， 再取英文名 然后中文名
            const name =
              reagentInfo?.abbreviation ||
              reagentInfo?.name ||
              reagentInfo?.cnname;
            reagentOptions.push({
              value: reagentId,
              label: name,
            });
          });
          tempOptions.push({
            label: lang["langreagent"],
            options: reagentOptions,
          });
        }
        setOptions(tempOptions);
      }
    }, [open, currentDesigner, reactionDrawerData]);

    return (
      <Modal
        title={
          <div>
            <span>{lang["langaddreagentandtemptime"]}</span>
            <span>
              <Space style={{ float: "right", marginRight: "16px" }}>
                <Button type="primary" onClick={addAll}>
                  {lang["langaddallreagents"]}
                </Button>
              </Space>
            </span>
          </div>
        }
        open={open}
        onOk={handleOk}
        onCancel={handleCancel}
      >
        <Content>
          <Select
            showSearch
            options={options}
            style={{ width: 470 }}
            onSelect={(value, record) => {
              onSelect(record);
            }}
            placeholder={lang["langpleaseselect"]}
            filterOption={(input, option: any) =>
              (option?.label ?? "").toLowerCase().includes(input.toLowerCase())
            }
          />
        </Content>
      </Modal>
    );
  })
);

const ReactionPlane: FC<any> = inject("store")(
  observer(({ store, edigReagentClick }: TProp) => {
    const {
      languageStore: { lang, langCur },
      reagentStore: { getReagentInfoById, allReagent },
      designerStore: {
        delDataReactorReagent,
        currentDesigner,
        changeEditReactorReagentData,
        changeShowReactorReagentDataModal,
        changeReactorStep,
        getDesignerInfo,
        reactionDrawerData,
        updateReactDesigner,
        changeReactionDrawerData,
        getReactDesignById,
      },
      shelfStore: { allShelf },
    } = store;

    const bottlesRef = useRef(null);

    const [columns, setColumns] = useState([] as ITColumns[]);

    const [dataSource, setDataSource] = useState([]);

    const [reactBottles, setReactBottles] = useState([]);

    const [reagentSourtList, setReagentSourtList] = useState([]);

    const [loading, setLoading] = useState(true);

    const items: MenuProps["items"] = [
      {
        key: "moveleft",
        icon: <CaretLeftOutlined />,
        label: lang["langcolumntoleft"],
      },
      {
        key: "moveright",
        icon: <CaretRightOutlined />,
        label: lang["langcolumntoright"],
      },
      {
        key: "clear",
        danger: true,
        icon: <ClearOutlined />,
        label: lang["langcleardatacolumn"],
      },
      {
        key: "remove",
        danger: true,
        icon: <DeleteOutlined />,
        label: lang["langdelcolumn"],
      },
    ];

    const tdItems: MenuProps["items"] = [
      {
        key: "autoinput",
        icon: <GroupOutlined />,
        label: lang["langautofillcolumn"],
      },
      {
        key: "remove",
        danger: true,
        icon: <DeleteOutlined />,
        label: lang["langdelete"],
      },
    ];

    const reactorTdClick = (
      data: any,
      reagentName: any,
      reactData: any,
      reagentIndex: number
    ) => {
      changeEditReactorReagentData({
        data,
        reactData,
        reagentInfo: reagentName,
        reagentIndex,
        // slotNameList,
      } as any);
      changeShowReactorReagentDataModal(true);
    };

    const tdDropClick = async ({
      item,
      record,
      key,
      reagentIndex,
      reactData,
    }: any) => {
      const { slotreagent, plate, _id } = reactData;
      if (key === "remove") {
        const { slotName } = record;
        if (!slotreagent) {
          return;
        }
        if (slotreagent[plate][slotName]) {
          slotreagent[plate][slotName][reagentIndex] = null;
        }
        await updateReactDesigner({
          id: _id,
          slotreagent,
        });
        const result = await getReactDesignById({ id: _id });
        if (result) {
          changeReactionDrawerData(result);
        }

        //   updateReactDesigner({
        //     id: _id,
        //     reagentsort: newReagentsort,
        //   });
      } else if (key === "autoinput") {
        const keys = Object.keys(slotreagent[plate]);
        let newSlotreagent = null;
        if (keys.length) {
          // 把keys数组反转
          keys.reverse().some((key) => {
            const reagentLis = slotreagent[plate][key];
            if (reagentLis && reagentLis.length > 0) {
              const reagentAmn = reagentLis[reagentIndex];
              if (reagentAmn) {
                const { amount } = reagentAmn;
                if (amount > 0) {
                  // 找到key到record.slotName的路径
                  const paths = getReversedBefore(
                    bottlesRef.current,
                    key,
                    record.slotName
                  );
                  if (paths.length > 0) {
                    let plantObj: any = {};
                    paths.forEach((path: string) => {
                      plantObj[path] = [];
                      plantObj[path][reagentIndex] = reagentAmn;
                    });

                    newSlotreagent = {
                      [plate]: plantObj,
                    };
                    return true;
                  }
                }
              }
            }
          });
        }

        if (newSlotreagent) {
          const nextSlotreagent = _.merge(slotreagent, newSlotreagent);
          await updateReactDesigner({
            id: _id,
            slotreagent: nextSlotreagent,
          });
          const result = await getReactDesignById({ id: _id });
          if (result) {
            changeReactionDrawerData(result);
          }
        }
      }
    };

    const TdRender = ({ item, record, reactData, reagentIndex }: any) => {
      const { slotreagent, plate } = reactData;
      const { slotName } = record;
      let tdText = null;
      let isTempTd = item === TEMPTIME;
      if (slotreagent) {
        const slotObj = slotreagent[plate];
        const reagentLis = slotObj[slotName];
        if (reagentLis) {
          const tdReagentInfo = reagentLis[reagentIndex];
          const { amount, unit, templature, time } = tdReagentInfo || {};
          if (!isTempTd) {
            if (amount > 0) {
              tdText = `${amount} ${unit}`;
            }
          } else {
            if (templature && time) {
              tdText = `${templature}℃/${time}h`;
            }
          }
        }
      }

      return (
        <>
          {isTempTd && slotName === "A1" && (
            <div
              className="reactor_td_temp"
              onClick={() => {
                reactorTdClick(record, item, reactData, reagentIndex);
              }}
            >
              {tdText}
            </div>
          )}
          {!isTempTd && (
            <div className="reactor_td">
              <div
                className="amount"
                onClick={() => {
                  reactorTdClick(record, item, reactData, reagentIndex);
                }}
              >
                {tdText}
              </div>
              <Dropdown
                menu={{
                  items: tdItems,
                  onClick: ({ key }) => {
                    tdDropClick({ item, record, key, reagentIndex, reactData });
                  },
                }}
              >
                <MoreOutlined style={{ cursor: "pointer" }} />
              </Dropdown>
            </div>
          )}
        </>
      );
    };

    const dropClick = async ({ reagentId, index, key }: any) => {
      const { reagentsort, _id, slotreagent, plate } = reactionDrawerData;

      const clearColData = () => {
        // 把slotreagent进行深拷贝
        if (slotreagent) {
          const newSlotreagent = _.cloneDeep(slotreagent);
          // 把slotName对应的列的数据设置为null
          const slotInfoObj = newSlotreagent[plate];
          const slotKeys = Object.keys(slotInfoObj);
          if (slotKeys.length > 0) {
            slotKeys.forEach((slotKey) => {
              newSlotreagent[plate][slotKey][index] = null;
            });
          }
          return newSlotreagent;
        }
        return undefined;
      };

      const changeColIndex = (key: string) => {
        // 把slotreagent进行深拷贝
        const newSlotreagent = _.cloneDeep(slotreagent);
        const slotInfoObj = newSlotreagent[plate];
        const slotKeys = Object.keys(slotInfoObj);
        if (slotKeys.length > 0) {
          slotKeys.forEach((slotKey) => {
            newSlotreagent[plate][slotKey] = swapElementPosition(
              newSlotreagent[plate][slotKey],
              index,
              key
            );
          });
        }
        return newSlotreagent;
      };

      if (key === "remove") {
        // 弹出确认删除提示
        Modal.confirm({
          title: lang["langconfirmdel"],
          onOk: async () => {
            // 删除reagentsort数组中index的元素
            reagentsort.splice(index, 1);
            const newReagentsort = [...reagentsort];
            const nextSlotreagent = clearColData();
            const param = {
              id: _id,
              reagentsort: newReagentsort,
              slotreagent: nextSlotreagent,
            };
            const res = await updateReactDesigner(param);
            if (!res) {
              changeReactionDrawerData({
                ...reactionDrawerData,
                reagentsort: newReagentsort,
                slotreagent: nextSlotreagent,
              });
            }
          },
        });
      } else if (key === "clear") {
        const nextSlotreagent = clearColData();
        const param = {
          id: _id,
          slotreagent: nextSlotreagent,
        };
        const res = await updateReactDesigner(param);
        if (!res) {
          changeReactionDrawerData({
            ...reactionDrawerData,
            slotreagent: nextSlotreagent,
          });
        }
      } else if (key === "moveleft") {
        if (index === 0) return;
        // 把reagentsort中的index位置的元素和前一个元素的交换位置
        const temp = reagentsort[index - 1];
        reagentsort[index - 1] = reagentsort[index];
        reagentsort[index] = temp;
        const newReagentsort = [...reagentsort];
        const param: any = {
          id: _id,
          reagentsort: newReagentsort,
          // slotreagent: nextSlotreagent,
        };
        let nextSlotreagent = null;
        if (slotreagent) {
          nextSlotreagent = changeColIndex(key);
          param.slotreagent = nextSlotreagent;
        }

        const res = await updateReactDesigner(param);
        if (!res) {
          let tempObj = {
            ...reactionDrawerData,
            reagentsort: newReagentsort,
            // slotreagent: nextSlotreagent,
          };
          if (nextSlotreagent) {
            tempObj.slotreagent = nextSlotreagent;
          }
          changeReactionDrawerData(tempObj);
        }
      } else if (key === "moveright") {
        if (index === reagentsort.length - 1) return;
        // 把reagentsort中的index位置的元素和后一个元素的交换位置
        const temp = reagentsort[index + 1];
        reagentsort[index + 1] = reagentsort[index];
        reagentsort[index] = temp;
        const newReagentsort = [...reagentsort];
        // const nextSlotreagent = changeColIndex(key);
        const param: any = {
          id: _id,
          reagentsort: newReagentsort,
          //   slotreagent: nextSlotreagent,
        };
        let nextSlotreagent = null;
        if (slotreagent) {
          nextSlotreagent = changeColIndex(key);
          param.slotreagent = nextSlotreagent;
        }
        const res = await updateReactDesigner(param);
        if (!res) {
          let tempObj = {
            ...reactionDrawerData,
            reagentsort: newReagentsort,
            // slotreagent: nextSlotreagent,
          };
          if (nextSlotreagent) {
            tempObj.slotreagent = nextSlotreagent;
          }
          changeReactionDrawerData(tempObj);
        }
      }
    };

    useEffect(() => {
      if (currentDesigner && allShelf.length && allReagent.length) {
        let defaultColumns: ITColumns[] = [];
        const reagentColumns: ITColumns[] = [];
        if (reactionDrawerData) {
          const { slotShelf, reactorSlotShelf, reagents } = currentDesigner;
          const { reagentsort, plate } = reactionDrawerData;

          //   let shelfName = "";
          let shelfName = slotShelf[plate].shelf;
          
          defaultColumns = [
            {
              title: `Reactor (${shelfName})`,
              dataIndex: "slotName",
              key: "slotName",
              width: 80,
              align: "center",
            },
            {
              title: "Slot",
              dataIndex: "plateName",
              key: "plateName",
              width: 80,
              align: "center",
            },
          ];

          const shelfInfo = allShelf.find((item) => item.name === shelfName);
          const bottleList = shelfInfo?.bottleList || [];
          const bottleNames: string[] = [];
          if (bottleList.length > 0) {
            bottleList.forEach((item) => {
              bottleNames.push(item.name);
            });
          }
          const newbottleNames: any = transformArray(bottleNames);
          setReactBottles(newbottleNames);
          bottlesRef.current = newbottleNames;
          setReagentSourtList(reagentsort);

          if (reagentsort && reagentsort.length) {
            reagentsort.forEach((reagentId: string, index: any) => {
              let name = "";
              if (reagentId === TEMPTIME) {
                name = TEMPTIME;
              } else {
                const reagentInfo: any = getReagentInfoById(reagentId);
                name = reagentInfo?.abbreviation ||
                  reagentInfo?.name ||
                  reagentInfo?.cnname || (
                    <span style={{ color: "red" }}>ERROR REAGENT</span>
                  );
              }

              reagentColumns.push({
                title: (
                  <div className="table_title">
                    <span></span>
                    <span>{name}</span>
                    <Dropdown
                      menu={{
                        items,
                        onClick: ({ key }) => {
                          dropClick({ reagentId, index, key });
                        },
                      }}
                    >
                      <MoreOutlined style={{ cursor: "pointer" }} />
                      {/* <Button size="small" icon={<MoreOutlined />} /> */}
                    </Dropdown>
                  </div>
                ),
                dataIndex: reagentId,
                key: index,
                align: "center",
                render: (data: any, record: any) => {
                  return (
                    <TdRender
                      data={data}
                      item={reagentId}
                      reagentIndex={index}
                      record={record}
                      reactData={reactionDrawerData}
                    />
                  );
                },
              });
            });
          }
        }
        reagentColumns.push({
          title: (
            <Tooltip title={lang["langaddnewcolumn"]} placement="topRight">
              <PlusSquareOutlined
                style={{ cursor: "pointer" }}
                onClick={edigReagentClick}
              />
            </Tooltip>
          ),
          dataIndex: "edit",
          key: "edit",
          align: "center",
          width: 20,
        });

        setColumns([...defaultColumns, ...reagentColumns]);
        setLoading(false);
      }
    }, [currentDesigner, allShelf, reactionDrawerData, allReagent]);

    useEffect(() => {
      let list: any = [];
      if (reactBottles.length > 0) {
        const { plate } = reactionDrawerData || {};
        reactBottles.forEach((bottleName) => {
          const obj = {
            key: bottleName,
            slotName: bottleName,
            plateName: plate,
          };
          list.push(obj);
        });
      }
      setDataSource(list);
    }, [reactBottles]);

    return (
      <Table
        dataSource={dataSource}
        columns={columns}
        bordered
        size="small"
        pagination={false}
        loading={loading}
      />
    );
  })
);

const ReactionExcelDesigner: FC<TProp | any> = ({
  store,
}: TProp): JSX.Element => {
  const {
    languageStore: { lang },
    designerStore: {
      currentDesigner,
      openReactionDrawer,
      changeOpenReactionDrawer,
      reactionDrawerData,
      getReactDesignerList,
    },
  } = store;

  const [title, setTitle] = useState(" ");

  const [showReagentHeaderModal, setShowReagentHeaderModal] = useState(false);

  const onClose = () => {
    changeOpenReactionDrawer(false);
    getReactDesignerList({ designer: currentDesigner?.id });
  };

  const closeReagentHeaderModal = () => {
    setShowReagentHeaderModal(false);
  };

  useEffect(() => {
    if (openReactionDrawer && reactionDrawerData) {
      const { name } = reactionDrawerData;
      setTitle(name);
    }
  }, [openReactionDrawer, reactionDrawerData]);

  const edigReagentClick = () => {
    setShowReagentHeaderModal(true);
  };

  return (
    <>
      <Drawer
        title={title}
        width="100%"
        closeIcon={false}
        onClose={onClose}
        open={openReactionDrawer}
        extra={
          <Space>
            <Button onClick={onClose}>{lang["langclose"]}</Button>
          </Space>
        }
      >
        <ReactionPlane edigReagentClick={edigReagentClick} />
      </Drawer>

      <ReagentHeaderModal
        open={showReagentHeaderModal}
        close={closeReagentHeaderModal}
      />
    </>
  );
};
export default inject("store")(observer(ReactionExcelDesigner));
